﻿using System.Diagnostics.CodeAnalysis;
using DimensionsHelper.Common.Utils;

namespace DimensionsHelper.LanguageService.Syntax;

/// <summary>
///     标识符
/// </summary>
public class Identifier : Expression
{
    internal Identifier(SyntaxNode? parent) :
        base(SyntaxKinds.Identifier, parent)
    {
    }


    internal Identifier(SyntaxNode? parent, string text) :
        base(SyntaxKinds.Identifier, parent)
    {
        Update(text);
    }


    /// <summary>
    ///     默认的空标识符，可用于初始化各种表达式。
    /// </summary>
    public static Identifier Default { get; } = new(null);


    /// <summary>
    ///     如果节点是宏扩展节点的原始节点，返回<see langword="true" />。
    /// </summary>
    public bool IsMacroExpansionSource => Parent?.IsNode(SyntaxKinds.MacroExpansion) == true;


    /// <summary>
    ///     如果标识符是空，返回<see langword="true" />。
    /// </summary>
    public override bool IsEmpty => Width == 0 || string.IsNullOrEmpty(Text);


    /// <summary>
    ///     如果标识符无效，返回<see langword="true" />
    /// </summary>
    public bool IsInvalid => GetFlags(SyntaxNodeFlags.InvalidIdentifier) || IsEmpty;


    /// <summary>
    ///     一般情况下，此属性值和<see cref="AbstractTextRange.Text" />相同，
    ///     仅当标识符通过宏展开得到时，此属性和<see cref="AbstractTextRange.Text" />不同，
    ///     此时，属性值为标识符的内容。
    /// </summary>
    public string Value { get; internal set; } = string.Empty;


    /// <summary>
    ///     如果是空值或默认值，返回true。
    /// </summary>
    public static bool IsDefaultOrEmpty([NotNullWhen(false)] Identifier? identifier)
    {
        return identifier == null
               || identifier.IsEmpty
               || ReferenceEquals(identifier, Default)
               || string.IsNullOrEmpty(identifier.Text);
    }
}


public static partial class NodeFactory
{
    public static Identifier CreateIdentifier()
    {
        return new Identifier(null);
    }


    // 不在此处检验标识符的有效性
    public static Identifier CreateIdentifier(string name)
    {
        return new Identifier(null, name);
    }


    public static Identifier CreateIdentifier(SourceNode source)
    {
        Identifier id = CreateIdentifier();
        id.UpdateFrom(source);
        id.Value = source.Text;
        return id;
    }
}


public static partial class NodeConverter
{
    public static Identifier ToIdentifier(Expression expression, SyntaxNode? parent)
    {
        if (expression.Is<Identifier>(out Identifier? identifier))
        {
            return identifier;
        }

        Identifier id = new(parent);
        id.UpdateFrom(expression);
        id.Value = expression.Text;

        if (!StringHelper.IsValidIdentifier(id.Text))
        {
            id.SetFlags(SyntaxNodeFlags.InvalidIdentifier);
        }

        return id;
    }
}